/**
 * 缺点：不能精细化更新，当修改name后应该只执行依赖name属性的effect，而不应该执行其他的effect
 */

class Dep {
  constructor() {
    this.subscribe = new Set()
  }
  depend() {
    if (activeEffect) {
      this.subscribe.add(activeEffect)
    }
  }
  notify() {
    this.subscribe.forEach((effect) => {
      effect()
    })
  }
}

// targetMap的键为对象，值为Map，值的Map的键为对象的属性，值为该属性的依赖
const targetMap = new WeakMap()
/**
 * 添加对象属性的依赖函数
 * @param {Object} target 对象
 * @param {string} key 对象的属性
 */
function getDep(target, key) {
  let depMap = targetMap.get(target)
  if (!depMap) {
    depMap = new Map()
    targetMap.set(target, depMap)
  }
  let dep = depMap.get(key)
  if (!dep) {
    dep = new Dep()
    depMap.set(key, dep)
  }
  return dep
}

let activeEffect = null
function watchEffect(effect) {
  activeEffect = effect
  // dep.depend() 不需要在这里收集依赖，而是在访问属性时自动调用get函数时收集依赖
  effect()
  activeEffect = null
}

// vue3 实现数据劫持
function reactive(raw) {
  return new Proxy(raw, {
    get(target, key) {
      const dep = getDep(target, key)
      dep.depend()
      return target[key]
    },
    set(target, key, newValue) {
      const dep = getDep(target, key)
      target[key] = newValue
      dep.notify()
    }
  })
}

const info = reactive({ name: 'zangsan', counter: 100 })

watchEffect(function doubleCounter() {
  console.log('dep1=>', info.counter * 2)
})
watchEffect(function powerCounter() {
  console.log('dep2=>', info.counter * info.counter)
})

watchEffect(function changename() {
  console.log('dep3=>', info.name)
})

// info.counter++ // 只会执行dep1, dep2, 不会执行dep3
info.name = 'lilei' // 只会执行dep3, 不会执行dep2
// dep.notify()
// info.name = 'lilei'
// dep.notify()
